/**
 * Copyright (C) 2011-2012 Rustam Bogubaev
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/gpl-3.0.html>.
 */
package com.google.code.myminimvc.controller;

import com.google.code.myminimvc.Configuration;
import com.google.code.myminimvc.Controller;
import com.google.code.myminimvc.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * Created by IntelliJ IDEA.
 * User: dev
 * Date: 8/30/11
 * Time: 12:47 AM
 */
public class ControllerEngine {
    private final Logger logger = LoggerFactory.getLogger(ControllerEngine.class);

    private HttpServletRequest request;
    private HttpServletResponse response;

    public ControllerEngine(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public Result execute() {
        try {
            Class<? extends Controller> clazz = resolveControllerClass();

            if (clazz == null) {
                return null;
            }

            return getControllerProxy(clazz).execute();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private Controller getControllerProxy(Class<? extends Controller> clazz) throws InstantiationException, IllegalAccessException {
        InvocationHandler invocationHandler = new ControllerInvocationHandler(request, response, clazz);

        return (Controller) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{Controller.class}, invocationHandler);
    }

    private Class<? extends Controller> resolveControllerClass() {
        String requestPath = request.getServletPath();

        Class<? extends Controller> clazz = Configuration.get().getUriMappings().get(requestPath);

        if (clazz == null) {
            logger.debug("unable to find controller class for " + requestPath + " path, so request and response passed to the next entity in the chain.");
            return null;
        }

        logger.debug("controller class found for path " + requestPath + ": " + clazz);

        return clazz;
    }
}
